package com.zijiebutiao.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zijiebutiao.utils.JwtUtils;
import com.zijiebutiao.utils.ResultVo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

//@Component
public class JwtFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String uri = request.getRequestURI();
//        System.out.println(uri);
        if(uri.contains("login" )   ||uri.contains("code") || uri.contains("swagger") || uri.contains("webjars") || uri.contains("api-docs")){
            filterChain.doFilter(request, response);
            return;
        }

        String token = request.getHeader("token");  // 获取请求头的认证信息
        if(null != token &&  !"".equals(token)) {
            try{
                // 解析Jwt信息
                Claims claims = JwtUtils.verifyToken(token);
                // 获取用户权限
                String authorities = claims.get("authorities", String.class);
                //获得用户名
                String username=claims.get("username",String.class);
                // Spring Security 的上下文中存储的是 UsernamePasswordAuthenticationToken对象
                // 第一个参数是用户名，第二个参数是密码，不需要给，第三个参数是权限
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.commaSeparatedStringToAuthorityList(authorities));
                // 设置当前usernamePasswordAuthenticationToken的一些信息，这些信息会从当前request中抽取出来
                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(request));
                // 将usernamePasswordAuthenticationToken设置到 Security的上下文当中。
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                filterChain.doFilter(request, response);
                return;
            }catch (ExpiredJwtException expiredJwtException){
                //jwt过期了  假设jwt2小时过期， 签发时间是12：30分 --》过期时间14：30
                //假设用户在14：29分使用应用， 用了1分钟，提示重新登录。 给一个可以复活的时间
                long expireTime = expiredJwtException.getClaims().getExpiration().getTime();
                long nowTime = System.currentTimeMillis();
                if (nowTime - expireTime > 1000*60*60){
                    //过期时间太久了，重新登录
                }else{
                    //过期时间不太长,认为是可以登录.并且要更新浏览器端的token
                    Claims claims=expiredJwtException.getClaims();
                    String username= (String) claims.get("username");
                    String authorities= (String) claims.get("authorities");
                    Map<String,Object> map=new HashMap<>();
                    map.put("username",username);
                    map.put("authorities",authorities);
                    String newToken = JwtUtils.createToken(map, 60);
                    System.out.println("token被刷新—————————"+newToken+"———————————————————————————————————————————");
                    response.setHeader("Access-Control-Expose-Headers","refresh_token");
                    response.setHeader("refresh_token",newToken);
                    // Spring Security 的上下文中存储的是 UsernamePasswordAuthenticationToken对象
                    // 第一个参数是用户名，第二个参数是密码，不需要给，第三个参数是权限
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                            new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.commaSeparatedStringToAuthorityList(authorities));
                    // 设置当前usernamePasswordAuthenticationToken的一些信息，这些信息会从当前request中抽取出来
                    usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetails(request));
                    // 将usernamePasswordAuthenticationToken设置到 Security的上下文当中。
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                    filterChain.doFilter(request, response);
                    return;
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }

            ResultVo jsonResult=new ResultVo();
            jsonResult.setCode(10010);
            jsonResult.setErrorMsg("token认证失败");
            System.out.println("token数据异常，请联系管理员A");
            ObjectMapper objectMapper=new ObjectMapper();
            String jsonstr= objectMapper.writeValueAsString(jsonResult);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().print(jsonstr);

    }


}